/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.cef.spi.jsonser.base;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;

/** 动态属性集合序列化构件基类, 此基类实现了IDynamicPropSerItem接口 <see cref="IDynamicPropSerItem"/> */
public abstract class AbstractDynamicPropSetSerItem implements IDynamicPropSerItem {
  /** 动态属性是否需要自定义序列化反序列化. 对于string/double/long/DateTime/bool类型的动态属性, 如果没有特殊需要可以不必实现其自定义序列化反序列化. */
  public abstract boolean isCustomSerialize(String propName);

  /**
   * 将动态属性实际(后端)名称转换为序列化后的动态属性名, 如果不重写此方法则动态属性的后端名称与序列化后名称保持一致. 注意: 如果重写此方法请与GetActualPropName一起重写.
   * <see cref="GetActualItemName"/>
   */
  public String getSerializationItemName(String propName) {
    return propName;
  }

  /**
   * 将序列化后的动态属性名转换为动态属性实际(后端)名称, 如果不重写此方法则动态属性的后端名称与序列化后名称保持一致. 注意:
   * 如果重写此方法请与GetSerializationItemName一起重写. <see cref="GetSerializationItemName"/>
   */
  public String getActualItemName(String propName) {
    return propName;
  }

  /**
   * 对需要自定义序列化反序列化的动态属性执行数据序列化
   *
   * @param name 动态属性名
   * @param value 动态属性值
   * @param writer JsonWriter
   * @param serializer JsonSerializer
   */
  public abstract void customWriteItemValue(
      String name, Object value, JsonGenerator writer, SerializerProvider serializer);

  /**
   * 对需要自定义序列化反序列化的动态属性执行数据反序列化
   *
   * @param actualName 动态属性名
   * @param reader JsonReader
   * @param serializer JsonSerializer
   */
  public abstract Object customReadItemValue(
      String actualName, JsonParser reader, DeserializationContext serializer);

  /**
   * 对需要自定义序列化反序列化的动态属性执行变更集序列化
   *
   * @param name 动态属性名
   * @param value 动态属性值
   * @param writer JsonWriter
   * @param serializer JsonSerializer
   */
  public abstract void customWriteItemChange(
      String name, Object value, JsonGenerator writer, SerializerProvider serializer);

  /**
   * 对需要自定义序列化反序列化的动态属性执行变更集反序列化
   *
   * @param actualName 动态属性名
   * @param reader JsonReader
   * @param serializer JsonSerializer
   */
  public abstract Object customReadItemChange(
      String actualName, JsonParser reader, DeserializationContext serializer);

  public void writeItemValue(
      String name, Object value, JsonGenerator writer, SerializerProvider serializer) {
    if (isCustomSerialize(name)) {
      customWriteItemValue(name, value, writer, serializer);
    } else {
      try {
        writer.writeObject(value);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
  }

  public Object readItemValue(String name, JsonParser reader, DeserializationContext serializer) {
    String actualName = getActualItemName(name);
    if (isCustomSerialize(actualName)) {
      return customReadItemValue(actualName, reader, serializer);
    } else {
      return readSimpleValue(reader);
    }
  }

  public final void writeItemChange(
      String name, Object value, JsonGenerator writer, SerializerProvider serializer) {
    if (isCustomSerialize(name)) {
      customWriteItemChange(name, value, writer, serializer);
    } else {
      try {
        writer.writeObject(value);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
  }

  public Object readItemChange(String name, JsonParser reader, DeserializationContext serializer) {
    String actualName = getActualItemName(name);
    if (isCustomSerialize(actualName)) {
      return customReadItemChange(actualName, reader, serializer);
    } else {
      return readSimpleValue(reader);
    }
  }

  private static Object readSimpleValue(JsonParser reader) {
    try {
      switch(reader.getCurrentToken()) {
        case VALUE_STRING:
          return reader.getValueAsString();
        case VALUE_NUMBER_FLOAT:
          return reader.getValueAsDouble();
        case VALUE_NUMBER_INT:
          return reader.getValueAsInt();
        case VALUE_TRUE:
        case VALUE_FALSE:
          return reader.getValueAsBoolean();
        case VALUE_NULL:
          return null;
      }
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
    throw new RuntimeException("动态属性类型" + reader.getCurrentToken() + "不支持默认反序列化");
  }
}
